package ch.connection;

import java.util.HashMap;

/** Classe per la gestione della macchina a stati
 * 
 * @author Giovanni Franza - GPLv3 - 8/6/2011
 *
 */

public class StateManager {
	public static final Integer SAME = -2;
	public static final Integer CHANGE = -3;
	public static final Integer ABORT = -4;
	
	private HashMap<String,Action> hm = new HashMap<String,Action>();
	private String welcome = "";
	private String bye = "";
	private Integer maxState = 0;
	private Integer badState = -1;
	private Integer currentState = 0;
	private Integer addedState = 0;
	private Integer addedNewState = 0;
	private String response = "";
	private char delimiter =' ';
	private Object auth;

	/** Construttore .
	 *
	 * @param welcome - messaggio di benvenuto
	 * @param bye - messaggio di addio
	 * @param delimiter - carattere tra il comando ed i parametri 
	 * 
	 */
	
	public StateManager( String welcome, String bye, char delimiter ) {
		this.welcome = welcome;
		this.bye = bye;
		this.delimiter = delimiter;
	}

	/** Construttore - usato per istanziare un nuovo sm (factory)
	 *
	 * @param stateManager - oggetto di gestione stati
	 * 
	 */
	
	public StateManager( StateManager sm ) {
		this.hm = sm.hm;
		this.welcome = sm.welcome;
		this.bye = sm.bye;
		this.maxState = sm.maxState;
		this.badState = sm.badState;
		this.currentState = sm.currentState;
		this.addedState = sm.addedState;
		this.addedNewState = sm.addedNewState;
		this.response = sm.response;
		this.delimiter = sm.delimiter;
	}

	/** Azione verso un nuovo stato
	 *
	 * @param data - comando ricevuto
	 * @param state - stato attuale
	 * 
	 */
	
	public void nextHop( String data, Integer state ) {
		int j=0;
		Action azione;
		Boolean stateNotChanged = false;
		String stdata = currentState.toString()+"|"+data.toLowerCase();
		for( j=0; j< data.length(); j++) {
			if( data.charAt( j ) == delimiter ) {
				stdata = currentState.toString()+"|"+data.toLowerCase().substring( 0,j );
				j++;
				break;
			}
		}
		azione = hm.get( stdata );
		if( azione == null ) {
			response = "";
			return;
		}
		if( azione.getNuovoStato() == currentState ) {
			stateNotChanged = true;
		}
		currentState = azione.getNuovoStato();
		response = azione.getConferma();

		Control control = azione.getVerifica();
		if( control != null ) {
			Object saveauth = auth;
			auth = control.verify( data.substring(j), auth );
			if( auth == null ) {
				currentState = badState;
				response = azione.getErrore();				
			}
			String resp;
			resp = control.getResponse( auth );
			if( resp != null ) {
				response = new String( resp );		
			}
			if( stateNotChanged ) {
				auth = saveauth;
			}
		}
		return;
	}
	
	/** Aggiunta di una azione nella catena di comandi della state machine
	 *
	 * @param Action - azione da inserire
	 * 
	 */
		
	public void add( Action azione ) {
		if( azione.getStato() == StateManager.CHANGE ) {
			addedState++;
		}
		azione.setStato( addedState );
		if( azione.getNuovoStato()  == StateManager.CHANGE ) {
			addedNewState++;
			maxState = addedNewState;
		}
		if( azione.getNuovoStato() == StateManager.ABORT ) {
			azione.setNuovoStato( badState );
		} else {
			azione.setNuovoStato( addedNewState );
		}
		hm.put( azione.getHash(), azione );
	}
	
	/** Verifica se la sequenza di comandi è finita correttamente
	 * 
	 */
	
	public boolean finishedOk( ) {
		if( currentState == maxState ) {
			return true;
		}
		return false;
	}
	/** Verifica se la sequenza di comandi è finita correttamente
	 * 
	 */
	public boolean error( ) {
		if( currentState == badState ) {
			return true;
		}
		return false;
	}
	
	/** Getter per lo stato corrente
	 * 
	 */
	
	public Integer getCurrentState(){
		return currentState;
	}

	/** Getter per la risposta al comando
	 * 
	 */
	
	public String getResponse(){
		return response;
	}

	/** Getter per la stringa di benvennuto
	 * 
	 */
	
	public String getWelcome(){
		return welcome;
	}
	
	/** Getter per la stringa di addio
	 * 
	 */
	
	public String getBye(){
		return bye;
	}

	/** Getter per l'oggetto ausiliario
	 * 
	 */

	public Object getUser() {
		return auth;
	}
}
